package controllers

import (
	"errors"
	"fmt"
	"github.com/XieWeikai/PlaceToGo/models"
	"github.com/XieWeikai/PlaceToGo/utils"
	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
	"net/http"
)

type LoginInput struct {
	Username string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

func Logout(c *gin.Context) {
	token := utils.ExtractToken(c)
	utils.GetTokenManager().DeleteToken(token)
	c.JSON(http.StatusOK, gin.H{"message": "logout successfully"})
}

func Register(c *gin.Context) {
	var u models.User

	if err := c.ShouldBind(&u); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if _, err := u.Save(); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	fmt.Println("User created successfully", u)

	c.JSON(http.StatusCreated, gin.H{"data": &u})
}

func Login(c *gin.Context) {
	var input LoginInput

	if err := c.ShouldBind(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	user, token, err := loginCheck(input.Username, input.Password)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "username or password is wrong"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"token": token, "username": user.Username, "role": user.UserType, "id": user.ID})
}

func checkPasswordHash(password, hash string) error {
	return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
}

func loginCheck(username string, password string) (*models.User, string, error) {

	var err error
	var u models.User

	u.Username = username
	if _, err := u.GetFirst(); err != nil {
		return nil, "", fmt.Errorf("username not found")
	}

	err = checkPasswordHash(password, u.Password)

	if err != nil && errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
		return nil, "", err
	}

	token, err := utils.GetTokenManager().GenerateToken(u.ID, u.UserType)

	if err != nil {
		return nil, "", err
	}

	return &u, token, nil

}
